#include "pch.h"
#include "GenList.h"

void InitGenList(GenList *gl)
{
	gl = NULL;
}

bool GetHSub(char *sub,char *hsub) {
	if (*sub == '\0' || strcmp(sub, "()") == 0)
	{
		hsub[0]='\0';
		return true;
	}
	size_t n = strlen(sub), i = 0, k = 0;
	char ch = sub[0];
	while (i < n && (k != 0 || ch != ','))
	{
		if (ch == '(')
			k++;
		else if (ch == ')')
			k--;
		i++;
		ch = sub[i];
	}
	if (i < n)
	{
		sub[i] = '\0';
		strcpy(hsub, sub);
		strcpy(sub, sub + i + 1);
	}
	else if (k != 0)
		return false;
	else {
		strcpy(hsub, sub);
		sub[0] = '\0';
	}
	return true;
}

void CreateGenList(GenList *g, const char *str)
{
	GenList gl = *g;
	size_t n = strlen(str);
	char *sub = (char*)calloc(n - 2, sizeof(char));
	assert(sub != NULL);
	char *hsub = (char*)calloc(n - 2, sizeof(char));
	assert(hsub != NULL);

	strncpy(sub, str + 1, n - 2);
	sub[n-2]='\0';

	if (gl == NULL)
	{
		gl = (GLNode*)malloc(sizeof(GLNode));
		assert(gl != NULL);
		gl->tag = HEAD;
		gl->hp = gl->tp = NULL;
	}

	GLNode *p = gl;
	while (strlen(sub) != 0)
	{
		p = p->tp = (GLNode*)malloc(sizeof(GLNode));
		assert(p != NULL);
		p->hp = p->tp = NULL;

		if (GetHSub(sub, hsub)) {
			if (hsub[0] == '(') {
				p->tag = CHILDLIST;
				CreateGenList(&p->hp, hsub);
			}
			else {
				p->tag = ATOM;
				p->atom = atoi(hsub);
			}
		}
	}
}


void ShowGenList(GenList *l) {
	GLNode *p = (*l)->tp;
	while (p != NULL)
	{
		if (p->tag == ATOM)
		{
			printf("%d,", p->atom);
			if (p->tp != NULL)
				printf(",");
		}			
		else if (p->tag == CHILDLIST)
			ShowGenList(&p->hp);

		p = p->tp;
	}
}

bool GenListEmpty(GenList *l)
{
	return (*l)->tp == NULL;
}

int GenListLength(GenList *l)
{
	size_t length = 0;
	GLNode *p = (*l)->tp;
	while (p != NULL)
	{
		length++;
		p = p->tp;
	}
	return length;
}

int GenListDepth(GenList *l)
{
	GenList gl = *l;
	if (gl->tp == NULL)
		return 1;
	GLNode *p = gl->tp;
	size_t maxdepth = 0, dep;
	while (p != NULL)
	{
		if (p->tag == CHILDLIST)
		{
			dep = GenListDepth(&p->hp);
			maxdepth = dep > maxdepth ? dep : maxdepth;
		}
		p = p->tp;
	}
	return maxdepth + 1;
}